home *** CD-ROM | disk | FTP | other *** search
/ Network Support Library / RoseWare - Network Support Library.iso / apidev / nodlst.arc / NODELIST.C < prev    next >
Text File  |  1989-12-15  |  16KB  |  475 lines

  1. /*                                                      */
  2. /*    NodeList -  Display the configuration of all nodes on the LAN*/
  3. /*                                                      */
  4. /*    by Charles Rose                                         */
  5. /*                                                      */
  6.  
  7. #include <stdio.h>
  8. #include <dos.h>
  9.  
  10. #include "ipx.h"
  11.  
  12. #define IPX_QUERY_SOCKET 0x5604
  13. #define MAX_RETRIES 5
  14. #define ADDED 0x55
  15. #define BRIDGE_DRIVER 1
  16. #define SHELL_DRIVER 2
  17. #define FIRST_SOCKET 0x8080
  18. #define SECOND_SOCKET 0x8181
  19.  
  20. /* Local Prototypes */
  21. void PrintDriverInfo( BYTE DriverType, WORD SessionSocket,
  22.             BYTE ShellComponentPosition, IPXAddress *Address );
  23. void printAddress(BYTE byte[], int count);
  24. void SetupECB( ECB *ECBptr, WORD *FragAddress, WORD Size );
  25. void QueryDriver( WORD connectionID );
  26. int InBridgeList( BYTE Node[6] );
  27. void IPXGetProcAddress(void (*proc)(),WORD *addressField);
  28. void IPXGetDataAddress(WORD *data,WORD *addressField);
  29.  
  30. IPXConfigRequest HoldRequest;        /* Request for Configuration Packets */
  31. IPXConfigReply     HoldReply[MAX_NODES];
  32. ECB          SendECB;
  33. ECB          RcvECB[MAX_NODES];
  34.  
  35. SPXHeader    EstSPXReq;        /* Establish connection w/ target */
  36. ECB          EstECBReq;
  37.  
  38. SPXInfoRequest   InfoRequest;        /* Make request of Shell/Bridge for Config */
  39. ECB          InfoRequestECB;
  40.  
  41. SPXDriverReply     InfoReply[10];    /* Receive response from Shell/Bridge */
  42. ECB          InfoReplyECB[10];
  43.  
  44. BYTE         targetNetwork[4] = { 0, 0, 0, 0 };
  45. BYTE         targetNode[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  46. WORD         targetSocket, socket;
  47.  
  48. BYTE         BridgeExclude[MAX_NODES][6];
  49. int          ExcludeCount = 0;
  50.  
  51. WORD         ticks;
  52.  
  53. void main()
  54. {
  55.       int         retcode, i, z, retries, isbridge;
  56.       IPXConfigReply     *reply;
  57.       BYTE        ShellComponentPosition;
  58.       WORD            SessionSocket, querySocket = IPX_QUERY_SOCKET;
  59.  
  60.       /* Print opening banner */
  61.       printf("NODELIST - Lists all nodes and their configurations.\n");
  62.       printf("Code and Article published in January 1990 NetWare Technical Journal\n");
  63.       printf("Copyright (c) 1989, McGraw-Hill, Inc.\n");
  64.       printf("Written by Charles Rose\n\n");
  65.  
  66.       /* Make sure IPX is active and ok */
  67.       if ( !IPXInitialize() )
  68.       {
  69.             printf("IPX must be loaded for this program to run.\n");
  70.             exit(1);
  71.       }
  72.  
  73.       /* Begin by opening a socket to send from */
  74.       socket = FIRST_SOCKET;
  75.       retcode = IPXOpenSocket( (BYTE*) &socket, TEMPORARY );
  76.       if ( retcode )
  77.       {
  78.             printf("Error opening socket %X.  Error = %X.\n",
  79.                   socket, retcode );
  80.             exit(1);
  81.       }
  82.  
  83.       /* Setup array of listening ECBs */
  84.       for ( i = 0; i < MAX_NODES; i++ )
  85.       {
  86.             SetupECB( &RcvECB[i], &HoldReply[i], sizeof( IPXConfigReply ) );
  87.             IPXListenForPacket( &RcvECB[i] );
  88.       }
  89.  
  90.       /* Send IPX Configuration Request */
  91.       SetupECB( &SendECB, &HoldRequest, sizeof( IPXConfigRequest ) );
  92.       HoldRequest.IPX.PacketType = 0;
  93.       HoldRequest.ExclusionCount = 0;
  94.  
  95.       /* Setup for broadcast mode: Place 0's in Network Address and*/
  96.       /* 0xFF's in Node Address                         */
  97.       movmem( targetNode, SendECB.ImmediateAddress, 6);
  98.       movmem( targetNetwork, HoldRequest.IPX.Destination.Network, 4);
  99.       movmem( targetNode, HoldRequest.IPX.Destination.Node, 6);
  100.  
  101.       /* Set to broadcast on the query Socket (456h) */
  102.       movmem( &querySocket, HoldRequest.IPX.Destination.Socket, 2);
  103.  
  104.       IPXSendPacket( &SendECB );
  105.       while ( SendECB.InUseFlag )
  106.             IPXRelinquishControl();
  107.  
  108.       if ( SendECB.CompletionCode )
  109.       {
  110.             printf( " Bad IPXSend, return = %x ", SendECB.CompletionCode );
  111.             exit(1);
  112.       }
  113.  
  114.       /* Wait a second between each retry (give it a chance to respond) */
  115.       ticks = IPXGetIntervalMarker();
  116.       printf("Broadcasting Configuration Request...\n");
  117.       while ( ( IPXGetIntervalMarker() - ticks ) < 18 )
  118.             ;
  119.  
  120.       /* Check list of ECBs and re-send MAX_RETRIES times to be sure*/
  121.       /* all stations have responded                    */
  122.       retries = 0;
  123.       while ( retries < MAX_RETRIES )
  124.       {
  125.             for ( i = 0; i < MAX_NODES; i++ )
  126.             {
  127.                   /* If this Receive ECB has received a good packet and*/
  128.                   /* we haven't already added it to our exclude lists,*/
  129.                   if ( !RcvECB[i].InUseFlag && !RcvECB[i].CompletionCode &&
  130.                          RcvECB[i].CompletionCode != ADDED )
  131.                   {
  132.                          /* Mark it as added */
  133.                          RcvECB[i].CompletionCode = ADDED;
  134.  
  135.                          /* Add it to the Exclusion Table if it's not a bridge */
  136.                          /* Clear bridge flag */
  137.                          isbridge = 0;
  138.  
  139.                          /* Check component list to see if there's a BRIDGE_DRIVER
  140. present */
  141.                          for ( z = 0; z < HoldReply[i].ComponentCount; z++ )
  142.                                if ( HoldReply[i].ComponentType[z] == BRIDGE_DRIVER
  143. )
  144.                                      isbridge++;
  145.  
  146.                          /* If no BRIDGE_DRIVER was found, add to the exclusion table
  147. */
  148.                          /* and update the number of exclusions                 
  149. */
  150.                          if ( !isbridge )
  151.                                movmem( HoldReply[i].IPX.Source.Node,
  152.                                      
  153. HoldRequest.ExclusionAddress[HoldRequest.ExclusionCount++],
  154.                                      6 );
  155.                   }
  156.             }
  157.  
  158.             /* Re-send the configuration request */
  159.             IPXSendPacket( &SendECB );
  160.             while ( SendECB.InUseFlag != OKAY )
  161.                   IPXRelinquishControl();
  162.  
  163.             if ( SendECB.CompletionCode != OKAY )
  164.             {
  165.                   printf( " Bad IPX Send, status = %x ", SendECB.CompletionCode);
  166.                   exit(1);
  167.             }
  168.  
  169.             /* Wait a second between each retry (give it a chance to respond) */
  170.             ticks = IPXGetIntervalMarker();
  171.             printf("Broadcasting Configuration Request...\n");
  172.             while ( ( IPXGetIntervalMarker() - ticks ) < 18 )
  173.                   ;
  174.  
  175.             retries++;
  176.       }
  177.  
  178.       /* Now iterate through list, contacting each node and producing*/
  179.       /* a report of each bridge and shell driver and their configuration     */
  180.  
  181.       /* First, show bridges                                  */
  182.  
  183.       printf( "=------------------------------------------------=\n");
  184.       printf( "=------------------------------------------------=\n");
  185.       printf( "          File Servers/Bridges\n");
  186.  
  187.       for ( i = 0; i < MAX_NODES; i++ )
  188.       {
  189.             /* If this ECB has not received anything, or if it received a*/
  190.             /* bad packet, move on to the next                */
  191.             if ( RcvECB[i].CompletionCode != ADDED )
  192.                   continue;
  193.  
  194.             reply = (IPXConfigReply*) RcvECB[i].FragmentDescriptor.Address[0];
  195.  
  196.             SessionSocket = reply->SPXDiagnosticSocket;
  197.  
  198.             for ( z = 0; z < reply->ComponentCount ; z++ )
  199.             {
  200.                   /* Ignore the shell drivers this go around  */
  201.                   if ( reply->ComponentType[z] == SHELL_DRIVER )
  202.                          continue;
  203.  
  204.                   if ( reply->ComponentType[z] == BRIDGE_DRIVER )
  205.                   {
  206.                          /* We know this node is a bridge, let's make*/
  207.                          /* sure we haven't contacted it before     */
  208.                          if ( !InBridgeList( HoldReply[i].IPX.Source.Node ) )
  209.                          {
  210.                                /* Add to Bridge List */
  211.                                movmem( HoldReply[i].IPX.Source.Node,
  212.                                      BridgeExclude[ExcludeCount++], 6 );
  213.  
  214.                                /* print banner */
  215.                                printf(
  216. "=------------------------------------------------=\n");
  217.                                printf( "Report for Node Address: ");
  218.                                printAddress( HoldReply[i].IPX.Source.Node, 6 );
  219.                                printf( "\n" );
  220.  
  221.  
  222.                                /* Print info on our Bridge */
  223.                                PrintDriverInfo( BRIDGE_DRIVER, SessionSocket, z,
  224.                                      &HoldReply[i].IPX.Source );
  225.                          }
  226.                   }
  227.             }
  228.       }
  229.  
  230.       /* Now show workstations/shells                         */
  231.  
  232.       printf( "=------------------------------------------------=\n");
  233.       printf( "             Workstations\n");
  234.  
  235.       for ( i = 0; i < MAX_NODES; i++ )
  236.       {
  237.             /* If this ECB has not received anything, or if it received a*/
  238.             /* bad packet, move on to the next                */
  239.             if ( RcvECB[i].CompletionCode != ADDED )
  240.                   continue;
  241.  
  242.             reply = (IPXConfigReply*) RcvECB[i].FragmentDescriptor.Address[0];
  243.  
  244.             SessionSocket = reply->SPXDiagnosticSocket;
  245.  
  246.             for ( z = 0; z < reply->ComponentCount ; z++ )
  247.             {
  248.                   /* Show the shell drivers this go around */
  249.                   if ( reply->ComponentType[z] == SHELL_DRIVER )
  250.                   {
  251.                          /* print banner */
  252.                          printf(
  253. "=------------------------------------------------=\n");
  254.                          printf( "Report for Node Address: ");
  255.                          printAddress( HoldReply[i].IPX.Source.Node, 6 );
  256.                          printf( "\n" );
  257.  
  258.                          PrintDriverInfo( SHELL_DRIVER, SessionSocket, z,
  259.                                &HoldReply[i].IPX.Source );
  260.                   }
  261.  
  262.  
  263.                   /* Skip the bridges this time */
  264.                   if ( reply->ComponentType[z] == BRIDGE_DRIVER )
  265.                          continue;
  266.  
  267.             }
  268.  
  269.       }
  270.  
  271.       printf( "=------------------------------------------------=\n");
  272.       printf( "=------------------------------------------------=\n");
  273.  
  274.       IPXCloseSocket( socket );
  275. }
  276.  
  277.  
  278. void PrintDriverInfo( BYTE DriverType, WORD SessionSocket, BYTE ShellComponentPosition,
  279.                   IPXAddress *Address )
  280. {
  281.       int   retcode, i, driver;
  282.       WORD    connectionID;
  283.  
  284.       /* This section, given a Session Socket, Component Position*/
  285.       /* and an IPXAddress structure,                         */
  286.       /* the routine should print the LAN Card type and configuration*/
  287.       /* info from the shells                           */
  288.  
  289.       /* Close old socket, open a new one */
  290.       IPXCloseSocket( socket );
  291.       socket = SECOND_SOCKET;
  292.       retcode = IPXOpenSocket( (BYTE*) &socket, TEMPORARY );
  293.       if ( retcode )
  294.       {
  295.             printf("Error opening socket.\n");
  296.             exit(1);
  297.       }
  298.  
  299.       /* Now, setup SPX connection.  First, post listens*/
  300.       /* You need a few here; tried w/ one and didn't work always*/
  301.       for ( i = 0; i < 10; i++ )
  302.       {
  303.             SetupECB( &InfoReplyECB[i], &InfoReply[i], sizeof( SPXDriverReply ) );
  304.             SPXListenForSequencedPacket( &InfoReplyECB[i] );
  305.       }
  306.  
  307.       /* Setup for Send SPX Connection Request */
  308.  
  309.       /* Initialize the ECB */
  310.       SetupECB( &EstECBReq, &EstSPXReq, sizeof( SPXHeader ) );
  311.       EstSPXReq.PacketType = 5; /* SPX Packet */
  312.  
  313.       /* Set Establish destination equal to config destination */
  314.       movmem( Address, &EstSPXReq.Destination, 10 );
  315.  
  316.       /* Now set socket to that obtained from Configuration Request */
  317.       movmem( &SessionSocket, EstSPXReq.Destination.Socket, 2);
  318.  
  319.       /* Make the connection (set retry to default (0) and set watchdog (1) */
  320.       retcode = SPXEstablishConnection( 0, 1, &connectionID, &EstECBReq );
  321.       if ( retcode )
  322.       {
  323.             printf("Can't Establish Connection, ret = %X\n", retcode );
  324.             exit(1);
  325.       }
  326.  
  327.       while ( EstECBReq.InUseFlag && !(kbhit()) );
  328.  
  329.       if ( EstECBReq.CompletionCode )
  330.       {
  331.             printf("Can't Establish Connection, Completion Code = %X\n",
  332.                   EstECBReq.CompletionCode );
  333.             exit(1);
  334.       }
  335.  
  336.       /* Connection has been established, now query shell */
  337.       SetupECB( &InfoRequestECB, &InfoRequest, sizeof( SPXInfoRequest ) );
  338.       InfoRequest.SPX.PacketType = 5; /* SPX Packet */
  339.  
  340.       InfoRequest.ComponentPosition = ShellComponentPosition;
  341.  
  342.       if ( DriverType == SHELL_DRIVER )
  343.       {
  344.             InfoRequest.RequestNumber = 0; /* Get Shell Driver Configuration */
  345.             QueryDriver( connectionID );
  346.       }
  347.       else
  348.       if ( DriverType == BRIDGE_DRIVER )
  349.       {
  350.             InfoRequest.RequestNumber = 1; /* Get Bridge Driver Configuration */
  351.  
  352.             for ( driver = 0; driver < 4; driver++ )
  353.             {
  354.                   InfoRequest.BridgeDriver = driver;
  355.                   printf("LAN %c:\n", 'A' + driver );
  356.                   QueryDriver( connectionID );
  357.             }
  358.       }
  359.  
  360.       SPXTerminateConnection( connectionID, &EstECBReq );
  361.  
  362.       while ( EstECBReq.InUseFlag && !kbhit() )
  363.             ;
  364.  
  365. }
  366.  
  367. void QueryDriver( WORD connectionID )
  368. {
  369.       int response, i;
  370.  
  371.       /* Send the Shell Driver query */
  372.       SPXSendSequencedPacket( connectionID, &InfoRequestECB );
  373.  
  374.       /* Now Check for a response, wait until there is one    */
  375.       /* Scan InfoReply's for !InUseFlag, key can be hit to abort */
  376.       response = 0;
  377.       while ( !response && !kbhit() )
  378.       {
  379.             for ( i=0; i < 10; i++ )
  380.             {
  381.                   if ( !InfoReplyECB[i].InUseFlag )
  382.                          response = i+1;
  383.             }
  384.       }
  385.       if ( kbhit() )
  386.       {
  387.             getch();
  388.             printf("Key was hit while waiting for shell to respond");
  389.             exit(1);
  390.       }
  391.  
  392.       /* If there is a bad response (such as when there are no more LAN*/
  393.       /* boards), then return                                       */
  394.       if ( InfoReply[response-1].CompletionCode )
  395.             return;
  396.  
  397.       /* Print configuration information */
  398.       printf("LAN Type is :\n");
  399.       printf("%s\n", InfoReply[response-1].LANDescription );
  400.  
  401.       printf("\nLAN Setup is :\n");
  402.       printf("%s\n", InfoReply[response-1].TextDescription );
  403.  
  404.       /* Finally, terminate the connection with this node */
  405.       SPXListenForSequencedPacket( &InfoReplyECB[response-1] );
  406. }
  407.  
  408. void printAddress(BYTE byte[], int count)
  409. {
  410.       int i;
  411.  
  412.       for (i=0; i<count; i++)
  413.             printf("%02X", byte[i]);
  414. }
  415.  
  416. void SetupECB( ECB *ECBptr, WORD *FragAddress, WORD Size )
  417. {
  418.       /* Initialize the fields necessary for all of our ECB's */
  419.  
  420.       ECBptr->ESRAddress = NULL;
  421.       ECBptr->InUseFlag = 0;
  422.       ECBptr->ECBSocket = socket;
  423.       ECBptr->FragmentCount = 1;
  424.  
  425.       IPXGetDataAddress( (WORD *)FragAddress,
  426.                      (WORD *)&ECBptr->FragmentDescriptor.Address );
  427.       ECBptr->FragmentDescriptor.Size = Size;
  428. }
  429.  
  430. int InBridgeList( BYTE Node[6] )
  431. {
  432.       int i, z, same;
  433.  
  434.       for ( i = 0; i < ExcludeCount; i++ )
  435.       {
  436.             same = 1;
  437.             for ( z = 0; z < 6; z++ )
  438.                   if ( Node[z] != BridgeExclude[i][z] )
  439.                   {
  440.                          same = 0;
  441.                          break;
  442.                   }
  443.             if ( same )
  444.                   return (1);
  445.       }
  446.  
  447.       return (0);
  448. }
  449.  
  450. void IPXGetProcAddress(proc,addressField)
  451. void (*proc)();
  452. WORD addressField[2];
  453. {
  454.       struct SREGS segregs;
  455.  
  456.       segread(&segregs);
  457.       segregs.es = segregs.ds;
  458.  
  459.       addressField[0] = (WORD) proc;
  460.       addressField[1] = (WORD) segregs.cs;
  461. }
  462.  
  463. void IPXGetDataAddress(data,addressField)
  464. WORD *data;
  465. WORD addressField[2];
  466. {
  467.       struct SREGS segregs;
  468.  
  469.       segread(&segregs);
  470.       segregs.es = segregs.ds;
  471.  
  472.       addressField[0] = (WORD) data;
  473.       addressField[1] = (WORD) segregs.ds;
  474. }
  475.